package com.gxa.community.customer.service.pay.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gxa.community.core.pojo.bo.cart.CartGoodsInfoBo;
import com.gxa.community.core.pojo.domain.OrderInfo;
import com.gxa.community.core.pojo.dto.cart.CartDTO;
import com.gxa.community.core.pojo.vo.cart.CartVO;
import com.gxa.community.core.pojo.vo.cart.GoodsVO;
import com.gxa.community.core.pojo.vo.order.TrhOrderVO;
import com.gxa.community.core.utils.R;
import com.gxa.community.customer.service.cart.impl.CartServiceImpl;
import com.gxa.community.customer.service.order.impl.OrderServiceImpl;
import com.gxa.community.customer.service.pay.PayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.util.*;

@Slf4j
@Service
@Transactional(rollbackFor = Throwable.class)
public class PayServiceImpl implements PayService {
    public static final String REDUCE_GOODS_STOCK = "reduceGoodsStock";
    public static final String UPDATE_CUSTOMER_COUPON = "updateCustomerCoupon";
    @Autowired
    //执行向消息队列中生产消息(发布)的
    private JmsMessagingTemplate jmsMessagingTemplate = null;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    private static final String SERVER_URL = "https://openapi.alipaydev.com/gateway.do";
    private static final String APP_ID = "2021000119673941";
    private static final String APP_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCVMlOseDM+mk79k1r9rkVnZFqsBuakZDgcBdjKboGCrrBcoX5WvpBJDMAtCXAdZpElSf3owJ+W0SNq+VFusyCTyMz7G77PISmKsXQyby6Rr9tZ/36kah3fw3y9wYJnVbz0GO9Nwd779VnuZvAQAg5azUQfRJ23e4B7xWSWfExOi0bpQe6zCCRZkzt6zWtS9iQWNxeuX0avTR6YGSvr2KACWqTnCw8mUcqg9tZmPiNyP07mkXBI93/eM9Ew/mAkU8/G4LargdpczWR/1T+MlCo5mBpy4fJmzgHpC7zDdNf5S54WclEmO4eXwSELSTUq3k1d+9FOncgVEB5AC3IHhwtHAgMBAAECggEAWXZ+GhNRlx5scz1i+G8BiwfwHutcbgLyaktPPcOZwUUC1+i2m0lVt5f/vIHGSrrwGg4ORP0MNSFfPYwWumyLAlMMJx7yAb3+7P2PkZZ9tDphK8w6olhHZaARMq/QhCozTaOOC3BPR4JN1NjA5rh05xni2WUJtbZGyvEIafxKvWV33KI8bFggzQwyDJ3RAvFVpgnsukGMvgY35faLlTlZkEuS6j+3gOnkYljzLeQZg0/5F8jET+wyol6V0Deyg5F0W3raHd81W/s8H+ET9cXhJz2smNnwWMmfIkQy88PjrBIcvtuXhGaVzx6s6mfAPrUKmCEl7G4tLeRDRFYBlp+3EQKBgQDQMoxHfll0pvRn7doeLIT8dCn/h3r1YwOLO1Yi+/fTu0j6jiMSJ43PcSLV1/kl2o1c9yUrZ8G0VBgY+/zaDISQZuZmiYQt+cWbeTQdZGk9aE8REft+JmImp1AeYFA4Df5gAcsjO3hM+r46Fdexsa6quQelFHBU+Njrn1WTH12tSwKBgQC3c9HhHUeBRNxNKvMiaUbY0FGUuxCfG55/NLIjw7fKqhRQvMRHQR/ZzkzLPKz9O0lFLUislVPz6V2oCIQrnSHI2OA0y0AjNqNOvqa8nnte95+MRiLIMMYr7lCUk7ID6hC+wiPwdf/I5rK/6vogtpTstGGjn+Q+g1qkJHypk5WIdQKBgFAZgnrnE4ebzCBIFEjTm/58usPC3f2WsIBavdML2dcuEO/Ey51qdla/EkXvp712jjicJULD0nSMfhDuseM6Oa5MyIvekGoX1Hzybqh4Pz0O6oyIvJdWMSDp8hsdtv858woA5qSRdsE3HwS97pRA5hBsy5IpgOZQLzTHwmauBJ5tAoGAdaVEtwS70l6CmMouWacB1BDkAGlmY2Km5hS5GM5ukv03Qf+ML9XHwznVbZBfr5XRixdbP7ITwJurgBLWD9IY1GCgh7rAStTDLcB91QAdRe2u15oyvAbrT0jpTB7bTj9QtcRyn8ZMXl3zy7e46Dmuj42t/+yNxrkd652qhGUsw/ECgYEAz3leAEm6IKLHxQN3RrACLFCm4ztWOIKyUzGBpGu3tlMMFfRg4lVXZKE0ltruLzml0MHpF63n9q47VSZcb5Hjbco+edL92kaFvNcw1IWx9h2HSBgl9d+LVmcZfvUSgsDYrAtyURzdEv4p1HgfH97NIdGij0her6erb0cLisWnjeg=";
    private static final String FORMAT = "json";
    private static final String CHARSET = "GBK";
    private static final String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl00NajlFnNTHobDQbQTUzC8Yo4KapP/9CUF46zLHjp4Mll+7zODKv+/3ZkOh0RCZqKT7gRDl3k1Gp3KoRBibhQ6uQMn+36cYupaNHGUcZXm+uaXT4kGANODfbiBX0vstnelFUe8Oq0ifG924cksDwpinUhyb3LkXtF+tzAUbwGx7i7wQQ4N29UM9aOU5bkFdElW32kKBSJAlzqWBSrEc9xLoDxjK3dk+QKbh6bcTh5LqG7GFTOs6Q/uAQhBsqtSoFcslTUjUIuqHtc0BaM0qSFr+08uuGduhi76M5sAWtLq/ZCcHcVh316WkiwvKkIIH/bjjG3hUS6s3m7g1mOyviQIDAQAB";
    private static final String SIGN_TYPE = "RSA2";
    @Override
    public String orderPay(OrderInfo orderInfo) {

        AlipayClient alipayClient =  new DefaultAlipayClient( SERVER_URL, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE);  //获得初始化的AlipayClient
        AlipayTradePagePayRequest alipayRequest =  new  AlipayTradePagePayRequest(); //创建API对应的request
        alipayRequest.setReturnUrl( "http://kinggo.icu:8081/pay/payReturn" );
//        alipayRequest.setNotifyUrl( "http://kinggo.icu:8081/pay/payReturn" ); //在公共参数中设置回跳和通知地址
        alipayRequest.setBizContent( "{"  +
                "\"out_trade_no\":" + "\"" + orderInfo.getNos() + "\","  +
                "    \"product_code\":\"FAST_INSTANT_TRADE_PAY\","  +
                "    \"total_amount\":" + "\"" + orderInfo.getPayment() + "\","    +
                "    \"subject\":" + "\"" + orderInfo.getBuyerId() + "\","    +
                "    \"body\":\"暂无信息\","  +
                "    \"passback_params\":\"merchantBizType%3d3C%26merchantBizNo%3d2016010101111\","  +
                "    \"extend_params\":{"  +
                "    \"sys_service_provider_id\":\"2088511833207846\""  +
                "    }" +
                "  }" ); //填充业务参数
        String form= "" ;
        try  {
            form = alipayClient.pageExecute(alipayRequest).getBody();  //调用SDK生成表单
        }  catch  (AlipayApiException e) {
            e.printStackTrace();
        }
        return form;
    }

    @Override
    public String payReturn(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException, JsonProcessingException {

        /**
         * 在该接口使用消息队列，支付成功  则取修改后台相关数据，同时删除缓存中存在的该待支付订单
         */

        // 获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("utf-8"), "utf-8");
            params.put(name, valueStr);
        }
        log.info("params:{}",params);//查看参数都有哪些
        boolean signVerified = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE); // 调用SDK验证签名
//验证签名通过
        if(signVerified){
            // 商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
            // 付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
            log.info("商户订单号={}",out_trade_no);
            log.info("支付宝交易号={}",trade_no);
            log.info("付款金额={}",total_amount);
            //TODO 支付成功，修复支付状态,向消息队列放置支付成功的订单号
            jmsMessagingTemplate.convertAndSend("orderPaySuccess",out_trade_no);
            //若该笔订单是购物车中生成的，还要去删减购物车中相应的商品
            Object order = redisTemplate.opsForValue().get(OrderServiceImpl.TRH_ORDER_CACHE + out_trade_no);
            ObjectMapper objectMapper = new ObjectMapper();
            R r = objectMapper.readValue(order.toString(), R.class);
            TrhOrderVO trhOrderVO = (TrhOrderVO) r.get("data");
            OrderInfo orderInfo = trhOrderVO.getOrderInfo();
            Map<Integer, Integer> map = trhOrderVO.getMap();//map中key为商品编号，value为商品数量
            //获取该用户购物车信息
            Object userCartInfo = redisTemplate.opsForValue().get(CartServiceImpl.CART_INFO + orderInfo.getBuyerId());
            CartVO cartVO = objectMapper.readValue(userCartInfo.toString(), CartVO.class);
            List<GoodsVO> goodsVOList1 = cartVO.getGoodsVOList();
            List<GoodsVO> goodsVOList = objectMapper.convertValue(goodsVOList1, new TypeReference<List<GoodsVO>>() {
                @Override
                public Type getType() {
                    return super.getType();
                }
            });

            Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
            Iterator<Map.Entry<Integer, Integer>> iterator = entries.iterator();
            while (iterator.hasNext()){
                Map.Entry<Integer, Integer> entry =iterator.next();
                Integer goodsId = entry.getKey();
                for (GoodsVO goodsVO : goodsVOList) {
                    if (goodsId == goodsVO.getId()){
                        Integer quantity = goodsVO.getQuantity()-entry.getValue();
                        if (quantity == 0){
                            goodsVOList.remove(goodsVO);
                        }else {
                            goodsVO.setQuantity(quantity);
                        }
                    }
                }
            }
            if (CollectionUtils.isEmpty(goodsVOList)){
                //购物车空了   删除该购物车信息
                redisTemplate.delete(CartServiceImpl.CART_INFO+orderInfo.getBuyerId());
            }else{
                //更新购物车信息
                String s = objectMapper.writeValueAsString(cartVO);
                redisTemplate.opsForValue().set(CartServiceImpl.CART_INFO+orderInfo.getBuyerId(),s);
            }

            //支付成功后需要减去商品库存以及清楚该用户已经使用了的消费券（利用消息队列完成）
            jmsMessagingTemplate.convertAndSend(REDUCE_GOODS_STOCK,map);
            jmsMessagingTemplate.convertAndSend(UPDATE_CUSTOMER_COUPON,orderInfo.getCouponId());
            //同时删除缓存中该笔待支付订单
            redisTemplate.delete(OrderServiceImpl.TRH_ORDER_CACHE+out_trade_no);
            return "ok";//跳转付款成功页面
        }else{
            return "no";//跳转付款失败页面
        }

    }


    @Override
    public R refund(String orderNo, Double payment) throws AlipayApiException {

        AlipayClient alipayClient = new DefaultAlipayClient(SERVER_URL,APP_ID,APP_PRIVATE_KEY,FORMAT,CHARSET,ALIPAY_PUBLIC_KEY,SIGN_TYPE);
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        request.setBizContent("{" +
                "\"out_trade_no\":" + "\"" + orderNo + "\","  +
//                "    \"trade_no\":\"\uE0000e10692402c6425fbbc64e166336804e\"," +
                "    \"total_amount\":" + "\"" + payment + "\","    +
                "    \"refund_reason\":\"正常退款\"," +
                "    \"out_request_no\":\"HZ01RF001\"," +
                "    \"operator_id\":\"OP001\"," +
                "    \"store_id\":\"NJ_S_001\"," +
                "    \"terminal_id\":\"NJ_T_001\"" +
                "  }");
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            log.info("调用成功");
            return R.ok("退款成功！");
        } else {
            log.info("调用失败");
            return R.error(600,"退款失败!");
        }
    }
}

